package log

import (
	"fmt"
	. "git.oschina.net/yangdao/extlib/data_type"
	"strings"
)

type ILogHandler interface {
	Log(string, ...interface{})
	Close()
}

var DefaultLogger *Logger
var logHandlerCreateFunc map[string]func(IAssociative) ILogHandler

const (
	TagMode_Enable  = 0
	TagMode_Disable = 1
)

type Logger struct {
	logHandlers []ILogHandler
	Tags        map[string]bool
	TagMode     int
}

func InitDefaultLogger(configs IAssociative) *Logger {
	DefaultLogger = NewLogger(configs)
	return DefaultLogger
}

/*
{
  :handlers ["ConsoleLogHandler" "FileLogHandler"]
  :tag-mode :enable
  :tags ["hehe"]
}

*/
func NewLogger(configs IAssociative) *Logger {
	if configs == nil {
		return nil
	}
	retLogger := &Logger{}
	if configs.ContainsKey(":handlers") {
		handlerVec := configs.Get(":handlers").(*TypVector)
		retLogger.logHandlers = make([]ILogHandler, 0)
		for i := 0; i < handlerVec.Count(); i++ {
			handlerDic := handlerVec.Nth(i).(IAssociative)
			handlerName := handlerDic.Get(":name").(string)
			if logHandlerCreateFunc[handlerName] != nil {
				retLogger.logHandlers = append(retLogger.logHandlers, logHandlerCreateFunc[handlerName](handlerDic))
			}
		}
	}
	if configs.ContainsKey(":tag-mode") {
		strTagMode := configs.Get(":tag-mode").(string)
		switch strTagMode {
		case ":enable":
			retLogger.TagMode = TagMode_Enable
		case ":disable":
			retLogger.TagMode = TagMode_Disable
		}
	}
	if configs.ContainsKey(":tags") {
		tagArray := configs.Get(":tags").(*TypVector)
		retLogger.Tags = make(map[string]bool, tagArray.Count())
		for i := 0; i < tagArray.Count(); i++ {
			retLogger.Tags[tagArray.Nth(i).(string)] = true
		}
	}
	return retLogger
}

func (this *Logger) Log(tags string, logValue ...interface{}) {
	if this.logHandlers != nil {
		tagArr := strings.Split(tags, ",")
		switch this.TagMode {
		case TagMode_Enable:
			if this.Tags == nil || tagArr == nil {
				return
			}
			isHave := false
			for i := 0; i < len(tagArr); i++ {
				if hasTag, _ := this.Tags[tagArr[i]]; hasTag {
					isHave = true
				}
			}
			if isHave == false {
				return
			}
		case TagMode_Disable:
			if this.Tags != nil && tagArr != nil {
				for i := 0; i < len(tagArr); i++ {
					if hasTag, _ := this.Tags[tagArr[i]]; hasTag {
						return
					}
				}
			}
		}

		for i := 0; i < len(this.logHandlers); i++ {
			this.logHandlers[i].Log(tags, logValue...)
		}
	}

}

func Log(tags string, logValue ...interface{}) {
	if DefaultLogger == nil {
		fmt.Println(logValue...)
	} else {
		DefaultLogger.Log(tags, logValue...)
	}
}

func AddLogHandlerCreateFunc(name string, fn func(IAssociative) ILogHandler) {
	if logHandlerCreateFunc == nil {
		logHandlerCreateFunc = make(map[string]func(IAssociative) ILogHandler)
	}
	logHandlerCreateFunc[name] = fn
}

func Close() {
	if DefaultLogger != nil {
		for i := 0; i < len(DefaultLogger.logHandlers); i++ {
			DefaultLogger.logHandlers[i].Close()
		}
	}
}

/*

   LogHandler

	 ConsoleLogHandler

	 FileLogHandler

	 DBLogHandler

*/
